#ifndef _SOCK_EVENT_H
#define _SOCK_EVENT_H
#include <sys/time.h>

#define SOCK_FLAG_READ 0
#define SOCK_FLAG_WRITE 1
#define SOCK_FLAG_TIMEOUT 2
#define SOCK_FLAG_CLOSE 3
#define SOCK_FLAG_NONE -1

typedef struct {
	int total;
	int active;
	int stop;
	int kq;
	struct kevent *kqlst;    /* change buffer */
	struct kevent *ke;   /* event buffer */
	int kqmax;       /* max structs to buffer */
	int kqoff;       /* offset into the buffer */
	unsigned char *kqueue_state; /* keep track of the kqueue state */
	/* active event list */
	struct list_head active_list;
	/* free event list */
	struct list_head free_list;
}event_base_t;

typedef struct {
	int fd;
	int flag;
	void (*read_cb) (int, short, void *);
	void *read_data;
	void (*write_cb) (int, short, void *);
	void *write_data;
	void (*timeout_cb) (int, short, void *);
	void *timeout_data;
	int timeout;
	event_base_t *base;
	struct list_head list;
}event_t;

/* if flag is SOCK_FLAG_NONE, the event will be cleared */
extern int event_add(event_t *ev);
extern int event_del(event_t *ev);
extern int event_update(event_t *ev, short flag, void *data, \
				void (*cb)(int, short, void *), struct timeval *tv);
extern int event_set(event_t *ev, int fd, short flag, void *data, \
				void (*cb) (int, short, void *), struct timeval *tv);
#define event_timeout_set(ev, tv, data, cb) \
		event_set(ev, ev->fd, SOCK_FLAG_TIMEOUT, data, cb, tv);
extern event_t *event_new(event_base_t *base);
extern void event_clean(event_t *ev);
extern event_base_t * event_base_new();
extern void event_base_clean(event_base_t *base);
extern void event_base_set(event_t *ev, event_base_t *base);
extern void event_base_run(event_base_t *base);
extern void event_base_stop(event_base_t *base);
#endif
